package com.open.exam.businessservice;

import com.open.exam.common.CacheKey;
import com.open.exam.common.CommonFunction;
import com.open.exam.common.ExamSitePath;
import com.open.exam.databasemodel.*;
import com.open.exam.databasemodel.ExamRoom;
import com.open.exam.databasemodel.ExamSubject;
import com.open.exam.dto.AdminInfo;
import com.open.exam.enums.*;
import com.open.exam.examplan.*;
import com.open.exam.examplan.ExamSite;
import com.open.exam.mapper.ExamPlanInfoMapper;
import com.open.exam.mapper.ExamSubjectMapper;
import com.open.exam.service.ExamPaperService;
import com.open.exam.service.ExamPlanInfoService;
import com.open.exam.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 考试计划导入逻辑
 * @author 奶茶
 * Created by on 2018/9/25 11:33.
 */
@Service
public class ExamPlanBussinessService {

    private static final Logger logger = LoggerFactory.getLogger(ExamPlanBussinessService.class);

    @Autowired
    private ExamSubjectMapper examSubjectMapper;
    @Autowired
    private ExamPlanInfoMapper examPlanInfoMapper;
    @Autowired
    private ExamPaperService examPaperService;
    @Autowired
    private ExamPlanInfoService examPlanInfoService;


    @Value("${ExamSiteURL}")
    private String examSiteURL;
    @Value("${SystemAdmin}")
    private String systemAdmin;
    @Value("${MessageNotifyBaseUrl}")
    private String messageNotifyBaseUrl;
    @Value("${MessageNotifyUrl}")
    private String messageNotifyUrl;


    /**
     * 导入考试计划数据
     * @param examPlanUrl 考试计划文件地址(NASS/本地)
     * @param flag 是否为压测模式
     * @return
     */
    public void importExamPlanData(String examPlanUrl, Boolean flag){
        //判断考试计划文件是否存在
        File file = new File(examPlanUrl);
        if(!file.exists()){
            CommonFunction.notifyManager(messageNotifyBaseUrl,messageNotifyUrl,"考试计划文件不存在:" + examPlanUrl,systemAdmin.split(","));
        }else{
            //获取考试计划实体
            String fileContent = FileUtil.getFileContent(examPlanUrl);
            if(!StringUtils.isEmpty(fileContent)){
                ExamPlan examPlan = GsonUtil.fromJsonToObject(fileContent, ExamPlan.class);
                //校验计划包信息
                String progressInfo = CommonFunction.checkExamPlan(examPlan);
                if(progressInfo != null){
                    CommonFunction.notifyManager(messageNotifyBaseUrl,messageNotifyUrl,progressInfo,systemAdmin.split(","));
                }else{
                    if(examPlan.getPackageType().equals(PackageType.PlanPackage.getPrefix())){
                        //项目信息
                        ExamApp examApp = examPlan.getExamApp();
                        ExamSite examSite = examPlan.getExamSite();
                        //初始化adminInfo
                        AdminInfo adminInfo = new AdminInfo();
                        adminInfo.setAppID(examApp.getAppID());
                        adminInfo.setExamSiteID(examSite.getExamSiteID());
                        //初始化用户表
                        ExamAdminUser examAdminUser = new ExamAdminUser();
                        examAdminUser.setAccount(examApp.getAccount());
                        examAdminUser.setPassword(examApp.getPassword());
                        examAdminUser.setManagerName(examApp.getManagerName());

                        String examPlanID = examPlan.getExamPlanID();
                        //查询当前计划状态
                        ExamPlanInfo info = examPlanInfoService.getExamPlanInfoByID(examApp.getAppID(), examPlanID);
                        if(info != null && info.getSysState().equals(ExamPlanSysState.DownLoadUNPaperCreated.getPrefix())){
                            downLoadPaperANDNotify(examPlanID,adminInfo,examApp);
                        }else{
                            //考点信息
                            com.open.exam.databasemodel.ExamSite examSiteDB = new com.open.exam.databasemodel.ExamSite();
                            examSiteDB.setExamSiteID(examSite.getExamSiteID());
                            examSiteDB.setExamSiteCode(examSite.getExamSiteCode());
                            examSiteDB.setExamSiteName(examSite.getExamSiteName());

                            //考试计划
                            ExamPlanInfo examPlanInfo = new ExamPlanInfo();
                            examPlanInfo.setAppID(examApp.getAppID());
                            examPlanInfo.setExamSiteID(examSite.getExamSiteID());
                            examPlanInfo.setExamPlanInfoID(examPlan.getExamPlanID());
                            examPlanInfo.setExamPlanCode(examPlan.getExamPlanCode());
                            examPlanInfo.setExamPlanName(examPlan.getExamPlanName());
                            examPlanInfo.setExamPlanType(examPlan.getApplicationRange().shortValue());
                            examPlanInfo.setBeginTime(examPlan.getBeginTime());
                            examPlanInfo.setEndTime(examPlan.getEndTime());
                            examPlanInfo.setExamMode(examPlan.getExamMode());
                            examPlanInfo.setLoginMode(examPlan.getLoginMode());
                            examPlanInfo.setMinExamTime(examPlan.getMinExamTime());
                            examPlanInfo.setRequiredSignIn(examPlan.getRequiredSignIn());
                            examPlanInfo.setSeatByNumberRequired(examPlan.getSeatByNumberRequired());
                            examPlanInfo.setSysState(ExamPlanSysState.Downloading.getPrefix());
                            examPlanInfo.setArrangeMode(examPlan.getArrangeMode());
                            examPlanInfo.setCapturePhotoMaxNumber(examPlan.getCapturePhotoMaxNumber());
                            examPlanInfo.setDeploymentMode(examPlan.getDeploymentMode());

                            //考场集合
                            List<ExamRoom> examRoomList = new ArrayList<>();
                            for (com.open.exam.examplan.ExamRoom examRoom:examSite.getExamRooms()) {
                                ExamRoom examRoomDBA = new ExamRoom();
                                examRoomDBA.setAppID(examApp.getAppID());
                                examRoomDBA.setExamRoomCode(examRoom.getExamRoomCode());
                                examRoomDBA.setExamRoomID(examRoom.getExamRoomID());
                                examRoomDBA.setExamRoomName(examRoom.getExamRoomName());
                                examRoomDBA.setExamSiteID(examSite.getExamSiteID());
                                examRoomDBA.setExamPlanInfoID(examPlan.getExamPlanID());
                                examRoomDBA.setMachineNum(examRoom.getMachineNumber());
                                examRoomDBA.setBakMachineNum(0);
                                examRoomList.add(examRoomDBA);
                            }

                            //科目
                            List<ExamSubject> examSubjectList = new ArrayList<>();
                            for (com.open.exam.examplan.ExamSubject examSubject:examSite.getExamSubjects()) {
                                ExamSubject examSubjectDBA = new ExamSubject();
                                examSubjectDBA.setAppID(examApp.getAppID());
                                examSubjectDBA.setSubjectType(Short.valueOf("1"));
                                //ExamMode
                                examSubjectDBA.setExamMode(examSubject.getExamMode().shortValue());
                                //ExamShowScoreMode
                                examSubjectDBA.setAutoCheckMode(examSubject.getAutoMarkMode().shortValue());
                                examSubjectDBA.setExamNotice(examSubject.getExamNotice());
                                examSubjectDBA.setExamPlanInfoID(examPlan.getExamPlanID());
                                examSubjectDBA.setExamSubjectID(examSubject.getSubjectID());
                                //PaperCreateMode
                                examSubjectDBA.setPaperCreateMode(examSubject.getPaperCreateMode().shortValue());
                                examSubjectDBA.setSubjectCode(examSubject.getSubjectCode());
                                //ExamPaperShowType
                                examSubjectDBA.setPaperShowMode(examSubject.getPaperShowMode().shortValue());
                                examSubjectDBA.setPreviewPaperTime(examSubject.getPreviewPaperTime());
                                examSubjectDBA.setTimeLimits(examSubject.getTimeLimits());
                                examSubjectDBA.setPaperShuffled(Short.valueOf(examSubject.getRequiredItemShuffled() ? "1":"0"));
                                examSubjectDBA.setRetryLimits(examSubject.getRetryLimits());
                                examSubjectDBA.setSubjectName(examSubject.getSubjectName());
                                examSubjectDBA.setSubjectPaperStatus(SubjectPaperStatus.UNDownload.getPrefix().shortValue());
                                examSubjectDBA.setExamNotice("");
                                examSubjectList.add(examSubjectDBA);
                            }

                            //场次
                            List<ExamScenes> examScenesList = new ArrayList<>();
                            for (ExamScene examScenes:examSite.getExamScenes()) {
                                ExamScenes examScenesDBA = new ExamScenes();
                                examScenesDBA.setAppID(examApp.getAppID());
                                examScenesDBA.setExamPlanInfoID(examPlan.getExamPlanID());
                                examScenesDBA.setExamSceneCode(examScenes.getExamSceneCode());
                                examScenesDBA.setExamSceneID(examScenes.getExamSceneID());
                                examScenesDBA.setSysState(Short.valueOf("0"));
                                examScenesDBA.setExamSceneName(examScenes.getExamSceneName());
                                examScenesDBA.setPlanBeginTime(examScenes.getBeginTime());
                                examScenesDBA.setPlanEndTime(examScenes.getEndTime());

                                examScenesList.add(examScenesDBA);
                            }

                            //考生
                            List<Examinee> examinerList = new ArrayList<>();
                            for (Examiner examiner:examSite.getExaminers()) {
                                Examinee examinerDBA = new Examinee();
                                //考生信息
                                examinerDBA.setAppID(examApp.getAppID());
                                examinerDBA.setCertificateNo(examiner.getCertificateNo());
                                //CertificateType
                                examinerDBA.setCertificateType(examiner.getCertificateType().shortValue());
                                examinerDBA.setExamCardNo(examiner.getExamCardNo().toUpperCase());
                                examinerDBA.setExamineeID(examiner.getExaminerID().toUpperCase());
                                examinerDBA.setPassword(examiner.getPassword());
                                examinerDBA.setPhotoResource(examiner.getPhoto() == null ? "":examiner.getPhoto());
                                examinerDBA.setExamineeName(examiner.getExaminerName());
                                examinerDBA.setExamPlanInfoID(examPlanID);
                                examinerDBA.setExamSiteID(examSite.getExamSiteID());
                                examinerDBA.setSex(examiner.getSex());
                                examinerDBA.setAccountType(Short.valueOf("0"));
                                examinerList.add(examinerDBA);
                            }

                            //编排
                            Map<String, Examiner> examinerDictionary = new HashMap<>();
                            for (Examiner examiner:examPlan.getExamSite().getExaminers()) {
                                examinerDictionary.put(examiner.getExaminerID(),examiner);
                            }

                            List<ExamineeArrange> examinerArrangeList = new ArrayList<>();
                            for (ExamArrange examArrange :examSite.getExamArranges()) {
                                for (ExamRoomArrange examRoomArrange : examArrange.getExamRoomArranges()) {
                                    Examiner examiner = examinerDictionary.get(examRoomArrange.getExaminerID());
                                    if(examPlan.getExamMode().equals(ExamMode.unifiedExam.getPrefix()) || examPlan.getExamMode().equals(ExamMode.preregisterExam.getPrefix())){
                                        ExamineeArrange examinerArrangeDBA = new ExamineeArrange();
                                        String planBeginTime = CommonFunction.examScenesFind(examScenesList, examArrange.getSceneID()).getPlanBeginTime();
                                        Integer timeLimits = CommonFunction.examSubjectFind(examSubjectList, examArrange.getSubjectID()).getTimeLimits();
                                        examinerArrangeDBA.setExamineeID(examRoomArrange.getExaminerID());
                                        examinerArrangeDBA.setExamPlanInfoID(examPlan.getExamPlanID());
                                        examinerArrangeDBA.setExamRoomID(examArrange.getExamRoomID());
                                        examinerArrangeDBA.setExamSceneID(examArrange.getSceneID());
                                        examinerArrangeDBA.setExamSubjectID(examArrange.getSubjectID());
                                        examinerArrangeDBA.setPlanBeginTime(planBeginTime);
                                        examinerArrangeDBA.setPlanEndTime(DateUtil.convertMillisecondToDateString(DateUtil.convertStringToDate(planBeginTime).getTime() + (timeLimits*60*1000)));
                                        examinerArrangeDBA.setSeatNo(examRoomArrange.getSeatNo());
                                        examinerArrangeDBA.setExamPaperID("");
                                        examinerArrangeDBA.setExamDate(planBeginTime);
                                        examinerArrangeDBA.setExamineeName(examiner.getExaminerName());
                                        examinerArrangeDBA.setAppID(String.valueOf(examApp.getAppID()));
                                        examinerArrangeList.add(examinerArrangeDBA);
                                    }else{
                                        ExamineeArrange examinerArrangeDBA = new ExamineeArrange();
                                        String planBeginTime = CommonFunction.examScenesFind(examScenesList, examArrange.getSceneID()).getPlanBeginTime();
                                        examinerArrangeDBA.setExamineeID(examRoomArrange.getExaminerID());
                                        examinerArrangeDBA.setExamPlanInfoID(examPlanID);
                                        examinerArrangeDBA.setExamRoomID(examArrange.getExamRoomID());
                                        examinerArrangeDBA.setExamSceneID(examArrange.getSceneID());
                                        examinerArrangeDBA.setExamSubjectID(examArrange.getSubjectID());
                                        examinerArrangeDBA.setPlanBeginTime(planBeginTime);
                                        examinerArrangeDBA.setPlanEndTime(examPlan.getEndTime());
                                        examinerArrangeDBA.setSeatNo(examRoomArrange.getSeatNo());
                                        examinerArrangeDBA.setExamDate(planBeginTime);
                                        examinerArrangeDBA.setExamPaperID("");
                                        examinerArrangeDBA.setExamineeName(examiner.getExaminerName());
                                        examinerArrangeDBA.setAppID(String.valueOf(examApp.getAppID()));
                                        examinerArrangeList.add(examinerArrangeDBA);
                                    }
                                }
                            }

                            //监考报告
                            List<ExamReport> examReportList = new ArrayList<>();
                            for (ExamArrange examArrange :examSite.getExamArranges()) {
                                ExamReport examReport = new ExamReport();
                                examReport.setAppID(examApp.getAppID());
                                examReport.setExamPlanInfoID(examPlanID);
                                examReport.setExamRoomID(examArrange.getExamRoomID());
                                examReport.setExamSubjectID(examArrange.getSubjectID());
                                examReport.setExamSceneID(examArrange.getSceneID());
                                examReport.setExamReport("");
                                examReport.setExamResult("");
                                examReport.setActuallyBeginTime(CommonFunction.examScenesFind(examScenesList, examArrange.getSceneID()).getPlanBeginTime());
                                examReport.setExamReportState(Short.valueOf("0"));
                                examReport.setExamResultState(Short.valueOf("0"));
                                examReport.setIfAccident(Short.valueOf("0"));
                                examReport.setIfUpload(Short.valueOf("0"));
                                examReport.setPaperVersion(0);
                                examReportList.add(examReport);
                            }

                            Integer integer = examPlanInfoService.addAll(examSiteDB, examApp, examAdminUser, examPlan.getExamSiteAppAccountRelation(), examPlanInfo, examRoomList, examScenesList, examSubjectList, examinerList, examinerArrangeList, examReportList, flag);
                            if(integer.equals(-1)){
                                CommonFunction.notifyManager(messageNotifyBaseUrl,messageNotifyUrl,"考试计划信息导入异常:" + examPlan.getExamPlanName(),systemAdmin.split(","));
                            }else{
                                downLoadPaperANDNotify(examPlanID,adminInfo,examApp);
                            }
                        }
                    }
                }
            }else{
                CommonFunction.notifyManager(messageNotifyBaseUrl,messageNotifyUrl,"考试计划文件内容为空！",systemAdmin.split(","));
            }
        }
    }

    /**
     * 下载考试科目试卷，并通知考务及相关人员
     * @param examPlanID
     * @param adminInfo
     */
    private void downLoadPaperANDNotify(String examPlanID, AdminInfo adminInfo, ExamApp examApp){
        //加载考试科目试卷
        downLoadSubjectPaper(examPlanID,adminInfo);
        //查询当前计划下的科目试卷信息是否已下载完毕
        List<Map<String, Object>> subjectInfo = examSubjectMapper.findFailDownloadSubjectInfo(examPlanID);
        Integer examPlanState = 0;
        if(ListUtil.isEmpty(subjectInfo)){
            //加载完成通知考务
            examPlanState = ExamPlanSysState.TestPaperCreated.getPrefix();
            HttpRequestUtils.sendPut(examSiteURL + "examplan/downloadexamplansuccess/" + examPlanID,null);
            CommonFunction.notifyManager(messageNotifyBaseUrl,messageNotifyUrl,"考试计划信息导入完成:" + examPlanID,(examApp.getManagerPhone() + "," +systemAdmin).split(","));
        }else{
            //加载科目试卷失败 发送短信给相关业务人员
            examPlanState = ExamPlanSysState.DownLoadUNPaperCreated.getPrefix();
            StringBuilder subjectNameBuilder = new StringBuilder("");
            subjectInfo.forEach(map -> {
                subjectNameBuilder.append(map.get("SubjectName")).append("-");
            });
            String message = "考试批次：" + subjectInfo.get(0).get("ExamPlanName").toString() + "中，科目：" + subjectNameBuilder.toString() + "加载失败，请联系系统管理员！";
            CommonFunction.notifyManager(messageNotifyBaseUrl,messageNotifyUrl,message,systemAdmin.split(","));
        }
        //修改考试计划状态
        ExamPlanInfo examPlanInfo = new ExamPlanInfo();
        examPlanInfo.setSysState(examPlanState);
        examPlanInfo.setAppID(adminInfo.getAppID());
        examPlanInfo.setExamSiteID(adminInfo.getExamSiteID());
        examPlanInfo.setExamPlanInfoID(examPlanID);
        examPlanInfoService.updateExamPlanSysState(examPlanInfo);
        examPlanInfo = null;
    }

    /**
     * 下载当前计划下所有未下载的科目试卷
     * @param examPlanID
     * @param adminInfo
     * @return
     */
    private void downLoadSubjectPaper(String examPlanID, AdminInfo adminInfo){
        StringBuilder prefixPath = new StringBuilder(ExamSitePath.rootPath).append("/").append(examPlanID).append("/").append(adminInfo.getExamSiteID()).append("/papers/");
        String appID = adminInfo.getAppID();

        //根据计划ID查询当前计划 当前计划的状态应为下载中或者计划已加载，科目试卷未完全生成状态
        ExamPlanInfo examPlanInfo = examPlanInfoMapper.getExamPlanInfoBySysState(appID, examPlanID,ExamPlanSysState.TestPaperCreated.getPrefix());
        if(examPlanInfo == null){
            CommonFunction.notifyManager(messageNotifyBaseUrl,messageNotifyUrl,"未查询到下载中的计划",systemAdmin.split(","));
        }else{
            //获取当前计划部署方式
            Integer deploymentMode = examPlanInfo.getDeploymentMode();
            //查询当前计划下未下载和已下载未生成试卷的所有的科目
            List<ExamSubject> subjectList = findExamSubjectPaperNotGenerate(appID, examPlanID);
            if(subjectList != null && !subjectList.isEmpty()){
                subjectList.forEach(examSubject ->{
                    examPaperService.downLoadExamSubjectPaper(adminInfo,examSubject,prefixPath,deploymentMode,examPlanID);
                });
                if(examPaperService.state(examPlanID)){
                    examPlanInfo.setSysState(ExamPlanSysState.TestPaperCreated.getPrefix());
                }else{
                    examPlanInfo.setSysState(ExamPlanSysState.DownLoadUNPaperCreated.getPrefix());
                }
                examPlanInfoMapper.updateExamPalnSyState(examPlanInfo);
            }
        }
    }

    /**
     * 查询当前计划下未下载和已下载未生成试卷的所有的科目
     * @param appID
     * @param examPlanID
     * @return
     */
    public List<ExamSubject> findExamSubjectPaperNotGenerate(String appID,String examPlanID){
        return examSubjectMapper.findSubjectList(appID, examPlanID,SubjectPaperStatus.DownloadCompleteAndPaperGenerate.getPrefix());
    }

}
